using System;
using System.ComponentModel;
using System.Windows.Forms;
using DevExpress.Utils;
using DevExpress.XtraTab;
using Guard = CSW.Framework.Common.Guard;

namespace CSW.Framework.UI.DevEx.UserControls
{
    /// <summary>
    /// DXTabUserControl.
    /// </summary>
    public class DXTabUserControl : XtraTabControl
    {
        private bool m_EventAdded;

        /// <summary>
        /// Initializes a new instance of the <see cref="DXTabUserControl"/> class.
        /// </summary>
        public DXTabUserControl()
        {
            base.HeaderButtons = TabButtons.Close;// | TabButtons.Next | TabButtons.Prev;
            base.HeaderButtonsShowMode = TabButtonShowMode.Always;
            base.ShowTabHeader = DefaultBoolean.True;
        }

        /// <summary>
        /// Loads a tab page.
        /// </summary>
        /// <param name="text">The text.</param>
        public T LoadTab<T>(string text) 
            where T : UserControl
        {
            bool isNew;
            return LoadTab<T>(text, out isNew);
        }

        /// <summary>
        /// Loads a tab page.
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="isNew">if set to <c>true</c> [is new].</param>
        /// <returns>The user control.</returns>
        public T LoadTab<T>(string text, out bool isNew) 
            where T : UserControl
        {
            Application.DoEvents();

            if (!m_EventAdded)
            {
                m_EventAdded = true;
                SelectedPageChanged += TabUserControl_SelectedPageChanged;
                CloseButtonClick += TabUserControl_CloseButtonClick;
            }

            Cursor.Current = Cursors.WaitCursor;
            try
            {
                foreach (XtraTabPage tabPage in TabPages)
                {
                    if (tabPage.Tag != null && tabPage.Tag.GetType() == typeof(T))
                    {
                        SelectedTabPage = tabPage;
                        ((T)tabPage.Tag).Focus();
                        isNew = false;
                        return (T)tabPage.Tag;
                    }
                }

                T userControl = (T)typeof(T).GetConstructor(Type.EmptyTypes).Invoke(null);
                XtraTabPage newTabPage = new XtraTabPage();
                newTabPage.Text = text;
                newTabPage.Tag = userControl;
                newTabPage.ShowCloseButton = DefaultBoolean.True;
                if (userControl is ISupportInitialize)
                    ((ISupportInitialize)userControl).BeginInit();
                newTabPage.Controls.Add(userControl);
                if (userControl is ISupportInitialize)
                    ((ISupportInitialize)userControl).EndInit();
                userControl.Dock = DockStyle.Fill;

                TabPages.Add(newTabPage);

                SelectedTabPage = newTabPage;
                userControl.Focus();

                isNew = true;
                return userControl;
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void TabUserControl_CloseButtonClick(object sender, EventArgs e)
        {
            XtraTabPage selectedTabPage = SelectedTabPage;
            if (selectedTabPage != null)
                TabPages.Remove(selectedTabPage);
        }

        private static void TabUserControl_SelectedPageChanged(object sender, TabPageChangedEventArgs e)
        {
            if (e.Page != null && e.Page.Tag is UserControl)
            {
                ((UserControl)e.Page.Tag).Focus();
            }
        }

        /// <summary>
        /// Focuses the tab containing the specified user control.
        /// </summary>
        /// <param name="userControl">The user control.</param>
        public void FocusTab(UserControl userControl)
        {
            Guard.ArgumentNotNull(userControl, "userControl");

            Application.DoEvents();

            Cursor.Current = Cursors.WaitCursor;
            try
            {
                foreach (XtraTabPage tabPage in TabPages)
                {
                    if (tabPage.Tag != null && tabPage.Tag.GetType() == userControl.GetType())
                    {
                        SelectedTabPage = tabPage;
                        userControl.Focus();
                        return;
                    }
                }
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }

            throw new Exception(string.Format("Tab of type '{0}' not found.", userControl.GetType()));
        }
    }
}
